package com.ifcar.app.weibo;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;

import net.oauth.OAuthAccessor;
import net.oauth.OAuthException;
import net.oauth.OAuthMessage;
import net.oauth.ParameterStyle;
import net.oauth.OAuth.Parameter;
import net.oauth.http.HttpMessage;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

/**
 *
 * @author chen-chao
 *
 */
public abstract class PostEntity {
    private final String METHOD = "POST";

    protected Properties oauthInfo;

    protected OAuthAccessor accessor;

    protected boolean autoRedirect;

    public PostEntity(OAuthAccessor accessor, Properties oauthInfo) {
        this(accessor, oauthInfo, false);
    }
    
    public PostEntity(OAuthAccessor accessor, Properties oauthInfo, boolean autoRedirect) {
        this.accessor = accessor;
        this.oauthInfo = oauthInfo;
        this.autoRedirect = autoRedirect;
    }
    
    protected abstract HttpEntity genEntity(Properties postInfo) throws Exception;

    public HttpPost getHttpPost(String url, Properties postInfo)
            throws Exception {
        HttpPost httppost = new HttpPost(url);
        // set auto direct by autoRedirect
        httppost.setParams(setAutoRedirect());

        // add header to post request
        Header[] headers = generateHeader(url, postInfo);
        if (headers != null) {
            for (Header header: headers) {
                httppost.addHeader(header);
            }
        }
        HttpEntity entity = genEntity(postInfo);
        httppost.setEntity(entity);
        return httppost;
    }

    protected HttpParams setAutoRedirect() {
        HttpParams params = new BasicHttpParams();
        HttpClientParams.setRedirecting(params, autoRedirect);
        return params;
    }

    protected abstract List<Parameter> getSignProperties(String url,
            Properties postInfo);

    protected Header[] generateHeader(String url, Properties postInfo)
            throws IOException, OAuthException, URISyntaxException {

        List<Parameter> list = getSignProperties(url, postInfo);
        OAuthMessage request = new OAuthMessage(METHOD, url, list, null);
        request.addRequiredParameters(accessor);

        HttpMessage httpRequest = HttpMessage.newRequest(request,
                ParameterStyle.AUTHORIZATION_HEADER);

        List<Header> newHeaders = afterProcessHeader(httpRequest, url, postInfo);
        Header[] headers = new Header[newHeaders.size()];
        headers = newHeaders.toArray(headers);
        return headers;
    }

    public static final String toString(Object from) {
        return (from == null) ? null : from.toString();
    }

    protected List<Header> afterProcessHeader(HttpMessage httpRequest,
            String url, Properties postInfo) {
        List<Header> newHeaders = new ArrayList<Header>();
        // remove post information from headers
        for (Entry<String, String> header: httpRequest.headers) {
            if (!header.getKey().equalsIgnoreCase("Authorization")) {
                continue;
            }
            newHeaders.add(new BasicHeader(header.getKey(), header.getValue()));
        }
        return newHeaders;
    }
}
